import { _decorator, Node, view } from 'cc';
import { App } from '../../App';
import { GlobalTemp } from '../../global/GlobalTemp';
import { Util } from '../../Util';
import { IViewCtrl, IViewDataProccesor, ViewId, ViewLayer } from '../common/view/IView';
import { ViewCtrlBase } from '../common/view/ViewCtrlBase';
import { ViewEvent } from '../common/view/ViewEvent';
import { EventMgr } from './EventMgr';
import { IMgr } from './IMgr';

export class ViewMgrData {
    ctrlMap: Map<ViewId, IViewCtrl & ViewCtrlBase> = new Map();
    dataProccesorMap: Map<ViewId, IViewDataProccesor> = new Map();
    viewTree: Map<ViewId, ViewId[]> = new Map();
    viewTreeParent: Map<ViewId/**子界面id */, ViewId/**父界面id */> = new Map();
    viewShow: Set<ViewId> = new Set();
}

export class ViewMgr implements IMgr {

    private _uiRoot: Node = null;
    get uiRoot(): Node {
        return this._uiRoot;
    }
    set uiRoot(r: Node) {
        this._uiRoot = r;
    }

    private _data: ViewMgrData = new ViewMgrData();
    get data(): ViewMgrData {
        return this._data;
    }

    eventMgr: EventMgr;

    util: Util;

    init() {
        this.eventMgr = App.ins.eventMgr;
        this.util = Util.ins;
    }
    finit() {

    }

    register(id: ViewId, ctrl: IViewCtrl & ViewCtrlBase, dataProccesor: IViewDataProccesor): IViewCtrl {
        this.data.ctrlMap.set(id, ctrl);
        this.data.dataProccesorMap.set(id, dataProccesor);
        return ctrl;
    }

    registerTree(viewId: ViewId, idArr: ViewId[] = []): void {
        for (const id of idArr) {
            this.data.viewTreeParent.set(id, viewId);
        }
        this.data.viewTree.set(viewId, idArr);
    }

    getChildId(viewId: ViewId): ViewId[] {
        return this.data.viewTree.get(viewId);
    }

    getParentViewId(viewId: ViewId): ViewId {
        return this.data.viewTreeParent.get(viewId);
    }

    /**获取最外层的界面id */
    getRootViewId(viewId: ViewId): ViewId {
        let root = viewId;
        let parentViewId = this.getParentViewId(viewId);
        while (parentViewId) {
            root = parentViewId;
            parentViewId = this.getParentViewId(parentViewId);
        }
        return root;
    }

    getFirstChildViewId(viewId: ViewId): ViewId {
        const childId = this.getChildId(viewId);
        if (!childId?.length) {
            return viewId;
        }
        return childId[0];
    }

    isViewShow(viewId: ViewId): boolean {
        return this.data.viewShow.has(viewId);
    }

    getViewChain(viewId: ViewId): ViewId[] {
        let chain = this.util.globalTemp.numberArr;
        chain.push(viewId);
        let parentViewId = this.getParentViewId(viewId);
        while (parentViewId) {
            chain.push(parentViewId);
            viewId = parentViewId;
            parentViewId = this.getParentViewId(viewId);
        }
        return chain;
    }

    getDeepCopyViewChain(viewId: ViewId): ViewId[] {
        return Util.ins.common.deepCopyArr(this.getViewChain(viewId));
    }

    openMulti(viewId: ViewId, params?: any): void {
        const ctrl = this.data.ctrlMap.get(viewId);

        console.log(" open multi ....  ", viewId, params);

        if (!ctrl) {
            console.error('...... view mgr open,ctrl not found  ....... ', viewId)
            return;
        }
        const dataProccesor = this.data.dataProccesorMap.get(viewId);
        dataProccesor?.setData(params);

        if (this.data.viewShow.has(viewId)) {
            console.error(" duplicate open view, view id  ", viewId);
        }

        /**窗口链 */
        let chain = this.getDeepCopyViewChain(viewId);
        let parentViewId = this.getParentViewId(viewId);
        while (parentViewId) {
            chain.push(parentViewId);
            viewId = parentViewId;
            parentViewId = this.getParentViewId(viewId);
        }

        console.log(" open multi chain  ...  ", chain);

        function openOne() {
            if (chain.length <= 0) {
                return;
            }
            let viewId = chain.pop();
            if (chain.length <= 0) {

                const pageIndex = this.getCtrl(viewId).baseData.pageIndex;
                let pageViewId = -1;
                if (pageIndex >= 0) {
                    pageViewId = this.getChildId(viewId)[pageIndex];
                } else {
                    /** todo 获取第一个开启的页签 */
                    const firstChildViewId = this.getFirstChildViewId(viewId);
                    if (firstChildViewId != viewId) {
                        pageViewId = firstChildViewId;
                    }
                }

                (pageViewId && pageViewId >= 0) && chain.push(pageViewId);
            }
            this.open(viewId).then(() => {
                openOne.call(this);
            })
        }

        openOne.call(this);
    }

    private async open(viewId: ViewId): Promise<any> {

        console.log(" open   ", viewId);

        const ctrl = this.data.ctrlMap.get(viewId);

        /**如果有父界面，则先关闭兄弟界面 */
        const parentViewId = this.getParentViewId(viewId);
        if (parentViewId) {
            /**关闭兄弟 */
            const childId = this.data.viewTree.get(parentViewId);
            for (const id of childId) {
                this.hide(id);
            }

            const index = childId.indexOf(viewId);
            const parentCtrl = this.getCtrl(parentViewId);
            if (parentCtrl && index >= 0) {
                parentCtrl.setMenuItemFocus(index, true);
            }
        }

        await ctrl.create();
        this.data.viewShow.add(viewId);

        console.log(" view mgr opennnnn  after  .... ", this.data.viewShow);

        return Promise.resolve();
    }

    hide(viewId: ViewId): void {
        if (!this.data.viewShow.has(viewId)) {
            return;
        }

        console.log(" view mgr ... hide ... ", viewId);

        /**先把自己的子界面 hide */
        const childId = this.getChildId(viewId);
        if (childId?.length) {
            for (const id of childId) {
                this.hide(id);
            }
        }

        const ctrl = this.getCtrl(viewId);
        ctrl.hide();
        this.data.viewShow.delete(viewId);

        const rootViewId = this.getRootViewId(viewId);
        if (viewId == rootViewId) {
            ctrl.onHideMyRoot();
        }


        console.log(" view mgr hide after  .... ", this.data.viewShow);

        /** todo dataProccesor?? */
        const dataProccesor = this.data.dataProccesorMap.get(viewId);
        dataProccesor?.setData(null);
    }

    getCtrl(viewId: ViewId): IViewCtrl & ViewCtrlBase {
        return this.data.ctrlMap.get(viewId);
    }

    getParentCtrl(viewId: ViewId): IViewCtrl {
        const parentId = this.data.viewTreeParent.get(viewId);
        return this.getCtrl(parentId);
    }

    // close(viewId: number): void {
    //     if (!this.data.viewShow.has(viewId)) {
    //         return;
    //     }
    //     const ctrl = this.getCtrl(viewId);
    //     ctrl.destroy();
    //     this.data.viewShow.delete(viewId);
    // }

    getLayer(layer: ViewLayer): Node {
        return this.uiRoot.children[layer];
    }


}







